#ifndef _SERVER_UDP_HPP_
#define _SERVER_UDP_HPP_

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cerrno>
#include <cstdbool>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

class ServerUDP
{
    static const int SIZE;
private:
    int _sockfd;
    uint16_t _port;
    std::string _ip;
public:
    ServerUDP(uint16_t port,const std::string &ip="")
        :_sockfd(0),_port(port),_ip(ip)
    {}

    ~ServerUDP()
    {}

    bool init()
    {
        // 创建网络套接字
        _sockfd=socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd<0)
        {
            std::cerr<<"socket error"<<std::endl;
            return false;
        }
        //std::cout<<"_sockfd: "<<_sockfd<<std::endl;

        // 2.进行绑定
        // 2.1 sockaddr_in的属性设置
        struct sockaddr_in local;
        memset(&local,0,sizeof(local)); // bzero
        local.sin_family=AF_INET;
        local.sin_port=htons(_port);
        local.sin_addr.s_addr=inet_addr(_ip.c_str());

        // 2.2 调用bind
        if(bind(_sockfd,(struct sockaddr*)&local,sizeof(local))<0)
        {
            std::cerr<<"bind error"<<std::endl;
            close(_sockfd);
            return false;
        }

        return true;
    }

    void start()
    {
        char buff[SIZE];

        struct sockaddr_in peer;
        memset(&peer,0,sizeof(peer));

        socklen_t slen=sizeof(peer);

        while(true)
        {
            // 1.获取数据
            ssize_t n=recvfrom(_sockfd,(void *)buff,sizeof(buff)-1,0,(struct sockaddr*)&peer,&slen);
            assert(n>=0);
            buff[n]='\0';
            // 2.进行分析
            FILE *pf=popen(buff,"r"); // 了解popen的使用
            if(nullptr==pf)
            {
                std::cerr<<"popen error: "<<errno<<" "<<strerror(errno)<<std::endl;
            }
            std::string str;
            memset((void *)buff,0,sizeof(buff));
            while(fgets(buff,sizeof(n),pf)!=nullptr)
            {
                str+=buff;
                // printf("--%s--\n",str.c_str());
            }
            // std::string echoStr;
            // while(fscanf(pf,"%s",buff)!=EOF) // 
            // {
            //     echoStr+=buff;
            // }
            // 3.返回数据
            sendto(_sockfd,str.c_str(),str.size(),0,(struct sockaddr *)&peer,slen);
        }
    }
    // void start()
    // {
    //     char buff[SIZE];

    //     struct sockaddr_in peer;z
    //     memset(&peer,0,sizeof(peer));

    //     socklen_t slen=sizeof(peer);

    //     while(true)
    //     {
    //         // 1.获取数据
    //         ssize_t n=recvfrom(_sockfd,(void *)buff,sizeof(buff)-1,0,(struct sockaddr*)&peer,&slen);
    //         assert(n>=0);
    //         buff[n]='\0';
    //         // 2.进行分析
    //         std::string ip=inet_ntoa(peer.sin_addr);
    //         uint16_t port=ntohs(peer.sin_port);
    //         fprintf(stdout,"[%s:%d]# %s\n",ip.c_str(),port,buff);
    //         // 3.返回数据
    //         socklen_t slen=sizeof(peer);
    //         sendto(_sockfd,(void *)buff,sizeof(buff),0,(struct sockaddr *)&peer,slen);
    //     }
    // }
};
const int ServerUDP::SIZE=1024;

#endif